
package com.huaweicloud.saaslanding.install.applicationservice.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huaweicloud.saaslanding.dao.common.entity.cloudservice.ElbInfo;
import com.huaweicloud.saaslanding.dao.common.entity.deployedresource.ElbResource;
import com.huaweicloud.saaslanding.dao.common.repository.cloudservice.ElbInfoBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.deployedresource.ElbResourceBaseMapper;
import com.huaweicloud.saaslanding.huawei.elb.api.ElbExclusiveApi;
import com.huaweicloud.saaslanding.huawei.elb.api.ElbShareApi;
import com.huaweicloud.saaslanding.huawei.elb.enumeration.LbAlgorithmEnum;
import com.huaweicloud.saaslanding.huawei.elb.enumeration.ProtocolEnum;
import com.huaweicloud.saaslanding.huawei.elb.model.Certificates;
import com.huaweicloud.saaslanding.huawei.elb.model.HeadersDto;
import com.huaweicloud.saaslanding.huawei.elb.request.exclusive.CertificatesExclusiveRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.exclusive.HealthMonitorsExclusiveRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.exclusive.ListenersExclusiveRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.exclusive.MembersExclusiveRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.exclusive.PoolsExclusiveRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.share.HealthMonitorsRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.share.ListenersRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.share.MembersRequest;
import com.huaweicloud.saaslanding.huawei.elb.request.share.PoolsRequest;
import com.huaweicloud.saaslanding.huawei.elb.response.share.CertificatesResponse;
import com.huaweicloud.saaslanding.huawei.elb.response.share.MembersResponse;
import com.huaweicloud.saaslanding.huawei.elb.response.share.PoolsResponse;
import com.huaweicloud.saaslanding.install.applicationservice.ElbService;
import com.huaweicloud.saaslanding.install.dto.ElbDto;
import com.huaweicloud.saaslanding.install.enumeration.ElbTypeEnum;
import com.huaweicloud.saaslanding.install.properties.Elb;
import com.huaweicloud.saaslanding.install.properties.ElbListener;
import com.huaweicloud.saaslanding.install.properties.ElbMember;
import com.huaweicloud.saaslanding.install.properties.ElbTls;
import com.huaweicloud.saaslanding.install.properties.Iam;
import com.huaweicloud.saaslanding.install.properties.Ingress;
import com.huaweicloud.saaslanding.install.properties.Ssl;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 功能描述
 *
 * @since 2022-11-29
 */
@Slf4j
@Component
public class ElbServiceImpl implements ElbService {

    @Value("${saaslanding-install.endpoint.iam}")
    private String iamEndPoint;

    @Value("${saaslanding-install.endpoint.elb}")
    private String elbEndPoint;

    @Resource
    private Iam iam;

    @Resource
    private ElbMember elbMember;

    @Resource
    private ElbInfoBaseMapper elbInfoBaseMapper;

    @Resource
    private ElbResourceBaseMapper elbResourceBaseMapper;

    @Resource
    private Elb elb;

    @Resource
    private Ssl ssl;

    @Resource
    private Ingress ingress;

    @Resource
    private ElbTls elbTls;

    @Resource
    private ElbListener elbListener;

    private HeadersDto getHeadersDto() {
        HeadersDto headersDto = new HeadersDto();
        headersDto.setIamEndpoint(iamEndPoint);
        headersDto.setIamDomainName(iam.getIamDomain());
        headersDto.setIamUserName(iam.getIamUser());
        headersDto.setIamPassword(iam.getIamPassword());
        headersDto.setProjectId(iam.getProjectId());
        headersDto.setElbEndpoint(elbEndPoint);
        return headersDto;
    }

    @Override
    public void createShareElb(ElbDto elbDto) {
        ElbInfo elbInfo = elbInfoBaseMapper.selectOne(new QueryWrapper<ElbInfo>().eq("instance_id", elb.getElbId()).eq("is_del",false));
        ElbResource elbResource = new ElbResource();
        elbResource.setElbId(elbInfo.getId());
        elbResource.setInstanceId(elb.getElbId());
        try {
            ListenersRequest listeners = new ListenersRequest();
            listeners.setLoadbalancerId(elb.getElbId());
            listeners.setProtocol(ProtocolEnum.HTTP.getType());
            listeners.setProtocolPort(elbDto.getListenersPort());
            listeners.setName("listener-" + elbDto.getName());

            PoolsRequest pools = new PoolsRequest();
            pools.setLbAlgorithm(LbAlgorithmEnum.ROUND_ROBIN.getType());
            pools.setLoadbalancerId(elbDto.getLoadbalancerId());
            pools.setProtocol(ProtocolEnum.HTTP.getType());
            pools.setName("server-group-" + elbDto.getName());
            pools.setDescription(elbDto.getName() + "的云服务器组");
            // 创建云服务器组
            PoolsResponse poolsResponse = ElbShareApi.addPools(getHeadersDto(), pools);
            elbResource.setPoolsId(poolsResponse.getId());

            StringBuilder memberIds = new StringBuilder();
            for (String str : elbMember.getAddress().split(";")) {
                MembersRequest members = new MembersRequest();
                members.setName("member-" + str.replace(".", ""));
                members.setProtocolPort(elbDto.getMemberPort());
                members.setAddress(str);
                members.setSubnetId(elbMember.getSubnetId());
                // 创建云服务器
                MembersResponse membersResponse =
                    ElbShareApi.addMember(getHeadersDto(), members, poolsResponse.getId());
                memberIds.append(membersResponse.getId()).append(";");
            }
            elbResource.setMemberIds(memberIds.substring(0, memberIds.length() - 1));

            HealthMonitorsRequest healthMonitors = new HealthMonitorsRequest();
            healthMonitors.setAdminStateUp(true);
            healthMonitors.setPoolId(poolsResponse.getId());
            healthMonitors.setDelay(10);
            healthMonitors.setTimeout(10);
            healthMonitors.setMaxRetries(10);
            healthMonitors.setType(ProtocolEnum.TCP.getType());
            healthMonitors.setName("health-monitors-" + elbDto.getName());
            // 创建健康检查
            elbResource.setHealthMonitorsId(ElbShareApi.addHealthMonitors(getHeadersDto(), healthMonitors).getId());

            if (ProtocolEnum.TERMINATED_HTTPS.getType().equals(elbDto.getListenersProtocol())) {
                Certificates certificates = new Certificates();
                certificates.setName(elbDto.getName() + "_certificates");
                certificates.setDescription(elbDto.getName() + "的tls证书");
                certificates.setType("server");
                certificates.setPrivateKey(elbDto.getPrivateKey());
                certificates.setCertificate(elbDto.getCertificate());
                // 创建ssl证书
                CertificatesResponse certificatesResponse = ElbShareApi.addCertificates(getHeadersDto(), certificates);

                elbResource.setSslId(certificatesResponse.getId());
                listeners.setProtocol(ProtocolEnum.TERMINATED_HTTPS.getType());
                listeners.setDefaultTlsContainerRef(certificatesResponse.getId());
            }

            listeners.setDefaultPoolId(poolsResponse.getId());
            // 创建监听器
            elbResource.setListenersId(ElbShareApi.addListeners(getHeadersDto(), listeners).getId());

            elbResourceBaseMapper.insert(elbResource);
        } catch (Exception e) {
            log.error("共享型elb初始化失败，进行elb资源回滚");
            deleteElb(elbResource, ElbTypeEnum.SHARE.getType());
        }
    }

    @Override
    public void deleteShareElb(String instanceId) {
        List<ElbResource> elbResourceList = elbResourceBaseMapper
            .selectList(new QueryWrapper<ElbResource>().eq("is_del", false).eq("instance_id", instanceId));
        for (ElbResource elbResource : elbResourceList) {
            deleteElb(elbResource, ElbTypeEnum.SHARE.getType());
        }
    }

    public void deleteElb(ElbResource elbResource, String elbType) {
        if (ElbTypeEnum.SHARE.getType().equals(elbType)) {
            if (StringUtils.isNotBlank(elbResource.getMemberIds())) {
                // 删除云服务器
                for (String memberId : elbResource.getMemberIds().split(";")) {
                    ElbShareApi.deleteMember(getHeadersDto(), memberId, elbResource.getPoolsId());
                }
            }

            // 删除健康检查
            if (StringUtils.isNotBlank(elbResource.getHealthMonitorsId())) {
                ElbShareApi.deleteHealthMonitors(getHeadersDto(), elbResource.getHealthMonitorsId());
            }

            // 删除云服务器组
            if (StringUtils.isNotBlank(elbResource.getPoolsId())) {
                ElbShareApi.deletePools(getHeadersDto(), elbResource.getPoolsId());
            }

            // 删除监听器
            if (StringUtils.isNotBlank(elbResource.getListenersId())) {
                ElbShareApi.deleteListeners(getHeadersDto(), elbResource.getListenersId());
            }

            // 删除ssl证书
            if (StringUtils.isNotBlank(elbResource.getSslId())) {
                ElbShareApi.deleteCertificates(getHeadersDto(), elbResource.getSslId());
            }
        } else if (ElbTypeEnum.EXCLUSIVE.getType().equals(elbType)) {
            // 删除云服务器
            if (StringUtils.isNotBlank(elbResource.getMemberIds())) {
                for (String memberId : elbResource.getMemberIds().split(";")) {
                    ElbExclusiveApi.deleteMember(getHeadersDto(), memberId, elbResource.getPoolsId());
                }
            }

            // 删除健康检查
            if (StringUtils.isNotBlank(elbResource.getHealthMonitorsId())) {
                ElbExclusiveApi.deleteHealthMonitors(getHeadersDto(), elbResource.getHealthMonitorsId());
            }

            // 删除云服务器组
            if (StringUtils.isNotBlank(elbResource.getPoolsId())) {
                ElbExclusiveApi.deletePools(getHeadersDto(), elbResource.getPoolsId());
            }

            // 删除监听器
            if (StringUtils.isNotBlank(elbResource.getListenersId())) {
                ElbExclusiveApi.deleteListeners(getHeadersDto(), elbResource.getListenersId());
            }

            // 删除ssl证书
            if (StringUtils.isNotBlank(elbResource.getSslId())) {
                ElbExclusiveApi.deleteCertificates(getHeadersDto(), elbResource.getSslId());
            }
        }
    }

    @Override
    public void createExclusiveElb(ElbDto elbDto) {
        ElbInfo elbInfo = elbInfoBaseMapper.selectOne(new QueryWrapper<ElbInfo>().eq("instance_id", elb.getElbId()).eq("is_del",false));
        ElbResource elbResource = new ElbResource();
        elbResource.setElbId(elbInfo.getId());
        elbResource.setInstanceId(elb.getElbId());
        try {
            ListenersExclusiveRequest listenersExclusiveRequestDto = new ListenersExclusiveRequest();
            listenersExclusiveRequestDto.setLoadbalancerId(elb.getElbId());
            if (ProtocolEnum.TERMINATED_HTTPS.getType().equals(elbDto.getListenersProtocol())) {
                CertificatesExclusiveRequest certificatesExclusiveRequestDto = new CertificatesExclusiveRequest();
                certificatesExclusiveRequestDto.setName(elbDto.getName() + "-certificates");
                certificatesExclusiveRequestDto.setDescription(elbDto.getName() + "的tls证书");
                certificatesExclusiveRequestDto.setType("server");
                certificatesExclusiveRequestDto.setPrivateKey(elbDto.getPrivateKey());
                certificatesExclusiveRequestDto.setCertificate(elbDto.getCertificate());
                // 创建ssl证书
                certificatesExclusiveRequestDto =
                    ElbExclusiveApi.addCertificates(getHeadersDto(), certificatesExclusiveRequestDto);

                elbResource.setSslId(certificatesExclusiveRequestDto.getId());
                listenersExclusiveRequestDto.setProtocol(ProtocolEnum.TERMINATED_HTTPS.getType());
                listenersExclusiveRequestDto.setDefaultTlsContainerRef(certificatesExclusiveRequestDto.getId());
            } else {
                listenersExclusiveRequestDto.setProtocol(ProtocolEnum.HTTP.getType());
            }

            PoolsExclusiveRequest poolsDto = new PoolsExclusiveRequest();
            poolsDto.setLbAlgorithm(LbAlgorithmEnum.ROUND_ROBIN.getType());
            poolsDto.setLoadbalancerId(elbDto.getLoadbalancerId());
            poolsDto.setName("server-group-" + elbDto.getName());
            poolsDto.setDescription(elbDto.getName() + "的云服务器组");
            if (ProtocolEnum.HTTPS.getType().equals(elbDto.getPoolsProtocol())) {
                poolsDto.setProtocol(ProtocolEnum.HTTPS.getType());
            } else {
                poolsDto.setProtocol(ProtocolEnum.HTTP.getType());
            }

            // 创建云服务器组
            poolsDto = ElbExclusiveApi.addPools(getHeadersDto(), poolsDto);
            elbResource.setPoolsId(poolsDto.getId());

            StringBuilder memberIds = new StringBuilder();
            for (String str : elbMember.getAddress().split(";")) {
                MembersExclusiveRequest membersDto = new MembersExclusiveRequest();
                membersDto.setName("member-" + str.replace(".", ""));
                membersDto.setProtocolPort(elbDto.getMemberPort());
                membersDto.setAddress(str);
                membersDto.setSubnetCidrId(elbMember.getSubnetId());
                // 创建云服务器
                memberIds.append(ElbExclusiveApi.addMember(getHeadersDto(), membersDto, poolsDto.getId()).getId())
                    .append(";");
            }
            if (memberIds.length() > 0) {
                elbResource.setMemberIds(memberIds.substring(0, memberIds.length() - 1));
            }

            HealthMonitorsExclusiveRequest healthMonitorsExclusiveRequestDto = new HealthMonitorsExclusiveRequest();
            healthMonitorsExclusiveRequestDto.setAdminStateUp(true);
            healthMonitorsExclusiveRequestDto.setPoolId(poolsDto.getId());
            healthMonitorsExclusiveRequestDto.setDelay(10);
            healthMonitorsExclusiveRequestDto.setTimeout(10);
            healthMonitorsExclusiveRequestDto.setMaxRetries(10);
            healthMonitorsExclusiveRequestDto.setType(ProtocolEnum.TCP.getType());
            healthMonitorsExclusiveRequestDto.setName("health-monitors-" + elbDto.getName());
            // 创建健康检查
            elbResource.setHealthMonitorsId(
                ElbExclusiveApi.addHealthMonitors(getHeadersDto(), healthMonitorsExclusiveRequestDto).getId());

            listenersExclusiveRequestDto.setProtocolPort(elbDto.getListenersPort());
            listenersExclusiveRequestDto.setName("listener-" + elbDto.getName());
            listenersExclusiveRequestDto.setDefaultPoolId(poolsDto.getId());
            // 创建监听器
            elbResource
                .setListenersId(ElbExclusiveApi.addListeners(getHeadersDto(), listenersExclusiveRequestDto).getId());

            elbResourceBaseMapper.insert(elbResource);
        } catch (Exception e) {
            log.error("独享型elb初始化失败，进行elb资源回滚");
            deleteElb(elbResource, ElbTypeEnum.EXCLUSIVE.getType());
        }
    }

    @Override
    public void deleteExclusiveElb(String instanceId) {
        List<ElbResource> elbResourceList = elbResourceBaseMapper
            .selectList(new QueryWrapper<ElbResource>().eq("is_del", false).eq("instance_id", instanceId));
        for (ElbResource elbResource : elbResourceList) {
            deleteElb(elbResource, ElbTypeEnum.EXCLUSIVE.getType());
        }
    }

    @Override
    public void initElb() {
        log.info("<-----------------开始初始化elb相关资源---------------->");
        if (ElbTypeEnum.EXCLUSIVE.getType().equals(elb.getElbType())) {
            createExclusiveElb(initUiElb());
        } else if (ElbTypeEnum.SHARE.getType().equals(elb.getElbType())) {
            createShareElb(initUiElb());
        }
        log.info("-----------------elb资源初始化成功------------------");
    }

    public ElbDto initImcGatewayElb() {
        ElbDto elbDto = new ElbDto();
        elbDto.setLoadbalancerId(elb.getElbId());
        elbDto.setListenersPort(elbListener.getGatewayImcPort());
        elbDto.setName("saasLanding-elb-gateway-imc");
        elbDto.setMemberPort(ingress.getNodePort());
        if (ssl.isEnabled()) {
            // 根据elb的类型设置前端elb南向的协议
            if (ElbTypeEnum.EXCLUSIVE.getType().equals(elb.getElbType())) {
                elbDto.setPoolsProtocol(ProtocolEnum.HTTPS.getType());
            } else {
                elbDto.setPoolsProtocol(ProtocolEnum.HTTP.getType());
            }
        } else {
            elbDto.setPoolsProtocol(ProtocolEnum.HTTP.getType());
        }
        elbDto.setListenersProtocol(ProtocolEnum.HTTP.getType());
        return elbDto;
    }

    @Override
    public void deleteElb() {
        log.info("<-----------------开始删除elb相关资源---------------->");
        if (ElbTypeEnum.EXCLUSIVE.getType().equals(elb.getElbType())) {
            deleteExclusiveElb(elb.getElbId());
        } else if (ElbTypeEnum.SHARE.getType().equals(elb.getElbType())) {
            deleteShareElb(elb.getElbId());
        }
        log.info("-----------------elb资源删除成功------------------");
    }

    /**
     * 初始化前端ELB资源
     *
     * @return elb初始化信息
     */
    public ElbDto initUiElb() {
        ElbDto elbDto = new ElbDto();
        elbDto.setLoadbalancerId(elb.getElbId());
        elbDto.setName("saasLanding-elb-ui");
        elbDto.setMemberPort(ingress.getNodePort());
        elbDto.setListenersPort(elbListener.getUiPort());
        if (ssl.isEnabled()) {
            elbDto.setListenersProtocol(ProtocolEnum.TERMINATED_HTTPS.getType());
            elbDto.setCertificate(elbTls.getUiCertificate());
            elbDto.setPrivateKey(elbTls.getUiPrivateKey());
        } else {
            elbDto.setListenersProtocol(ProtocolEnum.HTTP.getType());
        }
        // 根据监听器对应后端服务器组的协议
        elbDto.setPoolsProtocol(ProtocolEnum.HTTP.getType());
        return elbDto;
    }
}
